#include "controls.h"

namespace core
{



/*
 * @breif: image property name.
 */
const char * IMAGE_CONTROL_PROPERTY_SOURCE         = "src";





/*
 * @breif: grid image property name.
 */
const char * GRID_IMAGE_CONTROL_PROPERTY_LENGTH         = "grid-length";
const char * GRID_IMAGE_CONTROL_PROPERTY_INDEX          = "grid-index";
const char * GRID_IMAGE_CONTROL_PROPERTY_GRID           = "grid";
const char * GRID_IMAGE_CONTROL_PROPERTY_LEFT           = "grid-left";
const char * GRID_IMAGE_CONTROL_PROPERTY_TOP            = "grid-top";
const char * GRID_IMAGE_CONTROL_PROPERTY_RIGHT          = "grid-right";
const char * GRID_IMAGE_CONTROL_PROPERTY_BOTTOM         = "grid-bottom";





/*
 *@brief: imply dynamic create.
 */
IMPLY_DYNAMIC_CREATE( FaceDivision,     "div"         )
IMPLY_DYNAMIC_CREATE( FaceSpan,         "span"        )
IMPLY_DYNAMIC_CREATE( FaceBreak,        "br"          )
IMPLY_DYNAMIC_CREATE( FaceButton,       "button"      )
IMPLY_DYNAMIC_CREATE( FaceImage,        "image"       )
IMPLY_DYNAMIC_CREATE( FaceGridImage,    "grid-image"  )
IMPLY_DYNAMIC_CREATE( FaceGridButton,   "grid-button" )





/*
 * @breif: the span control.
 */
FaceSpan::FaceSpan()
{

}

void FaceSpan::Offset( int x, int y )
{
    for( FaceWindow *control = FirstChild();
         control;
         control = control->NextSibling() )
    {
        control->Offset( x, y );
    }
}

uint FaceSpan::OnLoad( uint wParam, uint lParam )
{
    XmlElement * element = (XmlElement *)wParam;
    FaceStyleManager * manager = (FaceStyleManager *)lParam;
    if( !element || !manager )
    {
        return false;
    }

    if( !ParseAttribute( element, manager ) )
    {
        return false;
    }

    if( !ParseInlineControls( element, manager ) )
    {
        return false;
    }

    ChangeWindowState( WINDOW_STATE_LOADED );
    return true;
}

uint FaceSpan::OnLayout( uint wParam, uint lParam )
{
    layout * parentLayout = (layout *)lParam;
    if( !parentLayout )
    {
        return false;
    }

    FaceStreamLayout layoutor;
    layoutor.BeforeInlineLayout( *parentLayout, *this );

    for( FaceWindow *control = FirstChild();
         control;
         control = control->NextSibling() )
    {
        if( !control->DispatchMessage( FM_LAYOUT, wParam, (uint)parentLayout ) )
        {
            break;
        }
    }

    layoutor.AfterInlineLayout( *parentLayout, *this );

    ChangeWindowState( WINDOW_STATE_LAYOUTED );

    return true;
}

uint FaceSpan::OnPaint( uint wParam, uint lParam )
{
    FacePainter * painter = ( FacePainter * )wParam;
    rect * clip = (rect *)lParam;

    DrawChild( painter, clip );

    ChangeWindowState( WINDOW_STATE_READY );

    return true;
}

bool FaceSpan::ParseInlineControls( const XmlElement *element, const FaceStyleManager *manager )
{
    if( !element || !manager )
    {
        return false;
    }

    const XmlNode *pNode = 0;
    while( 0 != (pNode = element->IterateChildren(pNode)) )
    {
        if( !pNode->Value() )
        {
            continue;
        }

        if( XmlNode::XML_ELEMENT == pNode->Type() )
        {
            const XmlElement * pElement = pNode->ToElement();
            const char * name = pElement->Value();
            if( strcmp( "span", name ) != 0 )
            {
                continue;
            }

            FaceWindow *control = (FaceWindow *) RuntimeClass::CreateObject( name );
            if( !control )
            {
                continue;
            }

            control->SetName( name );
            control->style_.Inherit( style_ );

            InsertEndChild( control );

            control->DispatchMessage( FM_LOAD, (uint)pElement, (uint)manager );
        }
        else if( XmlNode::XML_TEXT == pNode->Type() )
        {
            FaceText * text = new FaceText();
            if( !text )
            {
                return false;
            }

            uint lResult = 0;
            text->SetAttribute( "value", pNode->Value(), lResult );

            text->SetName( "text" );
            text->alpha_ = alpha_;

            text->style_ = style_;

            InsertEndChild( text );
        }
    }

    return true;
}





/*
 * @breif: the br control.
 */
FaceBreak::FaceBreak()
{

}

uint FaceBreak::OnLayout( uint, uint lParam )
{
    layout * parentLayout = (layout *)lParam;
    if( !parentLayout )
    {
        return false;
    }

    parentLayout->col = parentLayout->content.left;
    parentLayout->row = parentLayout->baseline;

    ChangeWindowState( WINDOW_STATE_LAYOUTED );

    return true;
}

uint FaceBreak::OnAdjust( uint, uint lParam )
{
    adjust *just = (adjust*)lParam;
    if( !just )
    {
        return false;
    }

    just->vertical = true;

    return true;
}

uint FaceBreak::OnPaint( uint, uint )
{
    ChangeWindowState( WINDOW_STATE_READY );

    return true;
}





/*
 * @breif: the image control.
 */
BEGIN_ATTRIBUTE_MAP(FaceImage)
    ATTRIBUTE_FILE( IMAGE_CONTROL_PROPERTY_SOURCE, file_, ATTRIBUTE_TRAIT_LAYOUT | ATTRIBUTE_TRAIT_PAINT )
    CHAIN_ATTRIBUTE_MAP(FaceWindow)
END_ATTRIBUTE_MAP()

FaceImage::FaceImage()
{

}

uint FaceImage::OnPaint( uint wParam, uint lParam )
{
    FacePainter * painter = ( FacePainter * )wParam;
    rect * clip = (rect *)lParam;

    int nclip = BeginPaint( painter, clip );
    if( nclip == 0 )
    {
        return false;
    }

    Draw( painter );

    if( !file_.empty() )
    {
        painter->DrawImage( file_, border_rect_, alpha_ );
    }

    DrawChild( painter, clip );

    EndPaint( painter, nclip );

    ChangeWindowState( WINDOW_STATE_READY );

    return true;
}





/*
 * @breif: the grid image control.
 */
BEGIN_ATTRIBUTE_MAP(FaceGridImage)
    ATTRIBUTE_FILE( IMAGE_CONTROL_PROPERTY_SOURCE, file_, ATTRIBUTE_TRAIT_LAYOUT | ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_LENGTH, grid_length_, ATTRIBUTE_TRAIT_LAYOUT | ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_INT( GRID_IMAGE_CONTROL_PROPERTY_INDEX, grid_index_, ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_GRID, grid_left_ = grid_top_ = grid_bottom_ = grid_right_, ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_TOP, grid_top_, ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_LEFT, grid_left_, ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_BOTTOM, grid_bottom_, ATTRIBUTE_TRAIT_PAINT )
    ATTRIBUTE_PIXEL( GRID_IMAGE_CONTROL_PROPERTY_RIGHT, grid_right_, ATTRIBUTE_TRAIT_PAINT )
    CHAIN_ATTRIBUTE_MAP(FaceWindow)
END_ATTRIBUTE_MAP()

FaceGridImage::FaceGridImage()
    : grid_length_( 0 )
    , grid_index_( 0 )
    , grid_left_( 0 )
    , grid_top_( 0 )
    , grid_bottom_( 0 )
    , grid_right_( 0 )
{

}

uint FaceGridImage::OnPaint( uint wParam, uint lParam )
{
    FacePainter * painter = ( FacePainter * )wParam;
    rect * clip = (rect *)lParam;

    int nclip = BeginPaint( painter, clip );

    if( nclip == 0 )
    {
        return true;
    }

    Draw( painter );

    if( !file_.empty() )
    {
        core::rect grid;
        grid.set( grid_left_, grid_top_, grid_right_, grid_bottom_ );
        painter->DrawGridImage( file_, border_rect_, grid, grid_length_, grid_index_, alpha_ );
    }

    DrawChild( painter, clip );

    EndPaint( painter, nclip );

    ChangeWindowState( WINDOW_STATE_READY );

    return true;
}





/*
 * @breif: the grid button control.
 */
FaceGridButton::FaceGridButton()
{

}

uint FaceGridButton::OnMouseHover( uint wParam, uint lParam )
{
    grid_index_ = 1;
    if( handle_delegate_ )
    {
        handle_delegate_->Update( border_rect_ );
    }

    return FaceGridImage::OnMouseHover( wParam, lParam );
}

uint FaceGridButton::OnMouseLeave( uint wParam, uint lParam )
{
    grid_index_ = 0;
    if( handle_delegate_ )
    {
        handle_delegate_->Update( border_rect_ );
    }

    return FaceGridImage::OnMouseLeave( wParam, lParam );
}

uint FaceGridButton::OnLButtonDown( uint wParam, uint lParam )
{
    grid_index_ = 2;
    if( handle_delegate_ )
    {
        handle_delegate_->Update( border_rect_ );
    }

    return FaceGridImage::OnLButtonDown( wParam, lParam );
}

uint FaceGridButton::OnLButtonUp( uint wParam, uint lParam )
{
    grid_index_ = 1;
    if( handle_delegate_ )
    {
        handle_delegate_->Update( border_rect_ );
    }

    return FaceGridImage::OnLButtonUp( wParam, lParam );
}



};